#include "XBaseServer.h"
#include "XBaseClient.h"
#include "XBaseError.h"
#include "XUtility.h"

XIMPL_LOGGER(XBaseServer, logger);

XBaseServer::XBaseServer()
{
	XLOG4CPLUS_GUARD( logger, __FUNCTION__ );
}
XBaseServer::~XBaseServer()
{
	XLOG4CPLUS_GUARD( logger, __FUNCTION__ );
}
int XBaseServer::execute(char* buffer, size_t buffer_size, size_t max_buffer_size)
{
	XLOG4CPLUS_GUARD( logger, __FUNCTION__ );
	
	int recv_size = -1;
	for (int i = 0; i < 2; i++) {
		if ( !is_connected() ) {
			reconnect();
			if ( !is_connected() ){
				break;
			}
		}
		
		int send_size = send_request(buffer, buffer_size);
		if (send_size != (int)buffer_size) {
			close();
			continue;
		}
		
		recv_size = recv_response(buffer, max_buffer_size);
		if (recv_size <= 0) {
			recv_size = -1;

			close();
			continue;
		}
		else {
			break;
		}
	}

	return recv_size;
}

XIMPL_LOGGER(XBaseServerManager, logger);

XBaseServer* XBaseServerManager::get(const std::string& table_name, const std::string& row_key)
{
	XLOG4CPLUS_GUARD( logger, __FUNCTION__ );

	XLOG4CPLUS_DEBUG(logger, "INPUT: table_name=" << table_name << ",HEX(row_key)=" << XUtility::str_2_hex( row_key ) );

	XLOG4CPLUS_DEBUG(logger, "_list.size()=" << _list.size());
	std::map<std::string, std::vector<XBaseServer> >::iterator tablet_list = _list.find(table_name);
	if (tablet_list == _list.end()) {
		mErrno = XBaseClient::PERR_TABLE_NOT_EXISTS;
		return NULL;
	}

	XLOG4CPLUS_DEBUG(logger, "tablet_list->second.size()=" << tablet_list->second.size());
	for (std::vector<XBaseServer>::iterator it=tablet_list->second.begin(); it!=tablet_list->second.end(); ++it) {
		XLOG4CPLUS_DEBUG(logger, "HEX(it->tablet_info()._start_row)=" << XUtility::str_2_hex( it->tablet_info().start_row() ) 
			<< ",HEX(it->tablet_info()._end_row)=" << XUtility::str_2_hex( it->tablet_info().end_row() ) );

		if ( ( it->tablet_info().start_row() <= row_key ) 
			&& ( it->tablet_info().end_row().empty() || row_key < it->tablet_info().end_row() ) ) {

			XLOG4CPLUS_DEBUG( logger, "it->tablet_info()._state=" << it->tablet_info()._state );
			if ( it->tablet_info().online() ) {
				return &(*it);
			}
		}
	}
	
	mErrno = XBaseClient::PERR_TABLET_NOT_EXISTS;
	return NULL;
}
void XBaseServerManager::put(XBaseServer& tablet)
{
    XLOG4CPLUS_GUARD( logger, __FUNCTION__ );
    XLOG4CPLUS_DEBUG(logger, "INPUT: tablet.tablet_info()._table_name=" << tablet.tablet_info().table_name()
        << ",HEX(tablet.tablet_info().row_start())=" << XUtility::str_2_hex( tablet.tablet_info().start_row() )
        << ",HEX(tablet.tablet_info().row_end())=" << XUtility::str_2_hex( tablet.tablet_info().end_row() ) );
    XLOG4CPLUS_DEBUG(logger, "_list.size()=" << _list.size());
    //DoZerg
    std::vector<XBaseServer> & vec = _list[tablet.tablet_info().table_name()];
    if(vec.empty())
        vec.push_back(tablet);
    else{
        XLOG4CPLUS_DEBUG(logger, "vec.size()=" << vec.size());
        std::vector<XBaseServer>::iterator it = vec.begin();
        for(;it != vec.end();++it){
            XLOG4CPLUS_DEBUG(logger, XUtility::str_2_hex( it->tablet_info().start_row() ) 
                << "," << XUtility::str_2_hex( it->tablet_info().end_row() ) );
            if ((it->tablet_info().start_row() == tablet.tablet_info().start_row()) &&
                (tablet.tablet_info().end_row() == it->tablet_info().end_row()))
            {
                *it = tablet;
                break;
            }
        }
        if(it == vec.end())
            vec.push_back(tablet);
        XLOG4CPLUS_DEBUG(logger, "vec.size()=" << vec.size());
    }
	//std::map<std::string, std::vector<XBaseServer> >::iterator tablet_list = _list.find(tablet.tablet_info().table_name());
	//if (tablet_list == _list.end()) {
	//	std::vector<XBaseServer> tablet_list;
	//	tablet_list.push_back(tablet);
	//	_list[tablet.tablet_info().table_name()] = tablet_list;
	//}
	//else {
	//	XLOG4CPLUS_DEBUG(logger, "tablet_list->second.size()=" << tablet_list->second.size());
	//	
	//	std::vector<XBaseServer>::iterator it = tablet_list->second.begin();
	//	for (; it!=tablet_list->second.end(); ++it) {
	//		XLOG4CPLUS_DEBUG(logger, XUtility::str_2_hex( it->tablet_info().start_row() ) 
	//			<< "," << XUtility::str_2_hex( it->tablet_info().end_row() ) );
	//		if ((it->tablet_info().start_row() == tablet.tablet_info().start_row()) 
	//			&& (tablet.tablet_info().end_row() == it->tablet_info().end_row())) {
	//			it->close();
	//			tablet_list->second.erase(it);
	//			break;
	//		}
	//	}
	//	if (it == tablet_list->second.end()) {
	//		tablet_list->second.push_back(tablet);
	//	}

	//	XLOG4CPLUS_DEBUG(logger, "tablet_list->second.size()=" << tablet_list->second.size());
	//}
	XLOG4CPLUS_DEBUG(logger, "_list.size()=" << _list.size());
}
void XBaseServerManager::remove(XBaseServer& tablet)
{
	XLOG4CPLUS_GUARD( logger, __FUNCTION__ );

	tablet.close();

	XLOG4CPLUS_DEBUG(logger, "INPUT: tablet.tablet_info()._table_name=" << tablet.tablet_info().table_name()
		<< ",tablet.tablet_info()._id=" << tablet.tablet_info().id() );

	XLOG4CPLUS_DEBUG(logger, "_list.size()=" << _list.size());
	std::map<std::string, std::vector<XBaseServer> >::iterator tablet_list = _list.find(tablet.tablet_info().table_name());
	if (tablet_list != _list.end()) {
		XLOG4CPLUS_DEBUG(logger, "tablet_list->second.size()=" << tablet_list->second.size());
		for (std::vector<XBaseServer>::iterator it=tablet_list->second.begin(); it!=tablet_list->second.end(); ++it) {	
			XLOG4CPLUS_DEBUG( logger, "it->tablet_info()._id=" << it->tablet_info()._id );
			
			if ( it->tablet_info().id() == tablet.tablet_info().id() ) {
				tablet_list->second.erase(it);
				break;
			}
		}
		
		if (tablet_list->second.empty()) {
			_list.erase(tablet_list);
		}
	}
	XLOG4CPLUS_DEBUG(logger, "_list.size()=" << _list.size());
}
void XBaseServerManager::remove(const std::string& table_name)
{
	XLOG4CPLUS_GUARD( logger, __FUNCTION__ );

	XLOG4CPLUS_DEBUG(logger, "INPUT:  table_name=" << table_name );

	XLOG4CPLUS_DEBUG(logger, "_list.size()=" << _list.size());
    std::map<std::string, std::vector<XBaseServer> >::iterator tablet_list = _list.find(table_name);
    if (tablet_list != _list.end()) {
        //DoZerg
        for(std::vector<XBaseServer>::iterator it=tablet_list->second.begin();it!=tablet_list->second.end();++it){
            XLOG4CPLUS_DEBUG( logger, "it->tablet_info()._id=" << it->tablet_info().id() );
            it->close();
        }
        _list.erase(tablet_list);
		//std::vector<XBaseServer>::iterator it=tablet_list->second.begin();
		//while ( it!=tablet_list->second.end() ) {
		//	XLOG4CPLUS_DEBUG( logger, "it->tablet_info()._id=" << it->tablet_info().id() );
		//	
		//	it->close();
		//	it = tablet_list->second.erase(it);
		//}
		//
		//if (tablet_list->second.empty()) {			
		//	_list.erase(tablet_list);
		//}
	}
	XLOG4CPLUS_DEBUG(logger, "_list.size()=" << _list.size());
}
void XBaseServerManager::close()
{
	XLOG4CPLUS_GUARD( logger, __FUNCTION__ );
	
	for ( std::map<std::string, std::vector<XBaseServer> >::iterator it = _list.begin();
		it != _list.end();
		++it ) {

		for (std::vector<XBaseServer>::iterator it_sub = it->second.begin();
			it_sub != it->second.end();
			++it_sub ) {

			it_sub->close();
		}
	}
}

